【企微开发最佳实践】Java企业微信应用开发SDK 您所在的位置:网站首页 wecom v30 【企微开发最佳实践】Java企业微信应用开发SDK

【企微开发最佳实践】Java企业微信应用开发SDK

#【企微开发最佳实践】Java企业微信应用开发SDK| 来源: 网络整理| 查看: 265

经过两年多业余时间断断续续的开发,基于Java Spring生态的企业微信API SDK类库wecom-sdk终于具备生产就绪能力了。该类库屏蔽了复杂性,高度抽象了请求模型,通用性和扩展性兼具。大大降低了开发人员的学习使用成本。

Github: https://github.com/NotFound403/wecom-sdkGitee: https://gitee.com/felord/wecom-sdk

现在已经开源并托管到Maven中央仓库,请使用最新版本:

               cn.felord         wecom-sdk         ${wecom.sdk.version}        目前自建应用已经能够满足大部分场景,第三方还在开发中。

接下来对核心的一些概念和用法进行一些介绍,方便大家入门。

入门

这里屏蔽了一些繁琐的步骤,开发者只需要做好配置即可调用。以下是调用企业群发API向客户群发送图文的例子:

  //① 应用参数组装 建议持久化并使用缓存层   AgentDetails externalAgent = DefaultAgent.nativeAgent("企业ID",                              "应用密钥",                              NativeAgent.EXTERNAL);   //② 定义缓存 全局定义一次即可   WeComTokenCacheable weComTokenCacheable = new Cache();   //③ 初始化API入口,建议注入Spring IoC   WorkWeChatApi wecom = new WorkWeChatApi(weComTokenCacheable);   //④ 检索具体的API   ExternalContactManager externalContactManager = wecom.externalContactManager(externalAgent);   //⑤ 组织参数   MsgTemplateRequest request = new MsgTemplateRequest(ChatType.GROUP);   ContentText text = new ContentText("测试企业向客户群发送信息");   request.setText(text);   Link link = new Link();   link.setTitle("百度一下");   link.setDesc("遇到问题,百度一下");   link.setUrl("https://www.baidu.com");   link.setPicurl("https://www.baidu.com/img/pc_79b50cf376490.png");   request.setAttachments(Collections.singletonList(new LinkMsgAttachment(link)));   request.setSender("zhangsan");   //⑥ 向企业微信服务器发起请求并获取响应结果   MsgTemplateResponse msgTemplateResponse = externalContactManager.messageApi()                                .addMsgTemplate(request);   Integer errcode = msgTemplateResponse.getErrcode();   String errmsg = msgTemplateResponse.getErrmsg();   String msgid = msgTemplateResponse.getMsgid();   List failList = msgTemplateResponse.getFailList();

步骤是不是非常简单,基本都是在组装参数。可能里面有几个概念大家会有疑惑,接下来我们对里面的一些重要概念进行一些说明。

AgentDetails

cn.felord.AgentDetails 是对应用的抽象描述,包含了企业IDcorpId,应用IDagentId以及密钥secret,绝大多数接口的调用会用到它,默认实现是DefaultAgent。如果是自建应用你可以这样初始化:

AgentDetails agent = new DefaultAgent("企业ID","应用密钥", "应用ID");

如果是内置应用,比如外部联系人应用:

AgentDetails external = DefaultAgent.nativeAgent("企业ID", "应用密钥", NativeAgent.EXTERNAL);

通常这些应用参数会存入数据库,然后我们需要通过企业ID和应用ID实现应用配置检索服务(可以增加缓存来降低数据库的检索压力):

(corpId,agentId) -> AgentDetails WeComTokenCacheable

这个主要定义企业微信AccessToken、corpticket和agentticket中继缓存。这里我使用了Spring Cache实现,你可以自由选择,但是要自行保证中继服务器数据一致性。

  public static class RedisWeComCacheable implements WeComTokenCacheable {     private static final String QYWX_TOKEN_CACHE = "token::qywx";     private static final String QYWX_CORP_TICKET_CACHE = "ticket::qywx::corp";     private static final String QYWX_AGENT_TICKET_CACHE = "ticket::qywx::agent"; ​     @CachePut(value = {QYWX_TOKEN_CACHE}, key = "#corpId.concat('::').concat(#agentId)")     @Override     public String putAccessToken(@NotNull String corpId, @NotNull String agentId, @NotNull String accessToken) {       return accessToken;    } ​     @Cacheable(value = {QYWX_TOKEN_CACHE}, key = "#corpId.concat('::').concat(#agentId)")     @Override     public String getAccessToken(@NotNull String corpId, @NotNull String agentId) {       return null;    } ​     @CachePut(value = {QYWX_CORP_TICKET_CACHE}, key = "#corpId.concat('::').concat(#agentId)")     @Override     public String putCorpTicket(@NotNull String corpId, @NotNull String agentId, @NotNull String corpTicket) {       return corpTicket;    } ​     @Cacheable(value = {QYWX_TOKEN_CACHE}, key = "#corpId.concat('::').concat(#agentId)")     @Override     public String getCorpTicket(@NotNull String corpId, @NotNull String agentId) {       return null;    } ​     @CachePut(value = {QYWX_AGENT_TICKET_CACHE}, key = "#corpId.concat('::').concat(#agentId)")     @Override     public String putAgentTicket(@NotNull String corpId, @NotNull String agentId, @NotNull String agentTicket) {       return agentTicket;    } ​     @Cacheable(value = {QYWX_TOKEN_CACHE}, key = "#corpId.concat('::').concat(#agentId)")     @Override     public String getAgentTicket(@NotNull String corpId, @NotNull String agentId) {       return null;    }  } WorkWeChatApi

WorkWeChatApi是企业微信API的唯一入口,推荐注入Spring IoC,然后就可以通过它的一系列方法来实现企业微信提供的功能了。例如通过手机号查询成员的企业微信userid:

AgentDetails agent = DefaultAgent.nativeAgent("企业ID", "通讯录secret", NativeAgent.CONTACT); ​ GenericResponse userIdByMobile = wecom.contactBookManager(agent)        .userApi()        .getUserIdByMobile("这里为手机号"); String userId = userIdByMobile.getData(); ​ 回调

回调的处理通过CallbackCrypto来负责,它屏蔽了验签、解密、异步处理等技术难点,你可以通过CallbackCryptoBuilder构建CallbackCrypto,并把CallbackCrypto注入Spring IoC。

CallbackCryptoBuilder

CallbackCryptoBuilder有几个关键点:

XmlReader  XML解析的抽象,框架默认提供了XStream实现,不喜欢的可以重新实现注入。Consumer 消费事件函数,用来处理回调数据。CallbackSettingsService 企业微信回调配置检索,用来检索回调的配置参数。ExecutorService 回调处理线程池,回调数据的处理是异步的,这里默认提供了一个名字为WECOM-CALLBACK-THREAD-POOL的线程池,你也可以自定义一个符合你实际配置的线程池。

参考示例:

  @Bean   public CallbackCrypto callbackCrypto(IEventRecordService eventRecordService,                     IWeCallbackSettingsService callbackSettingsService) {     return new CallbackCryptoBuilder(eventRecordService::handleCallbackEvent)        .build(callbackSettingsService::getByAgentIdAndCorpId);  } 回调示例

通用回调参考示例:

@RestController @RequestMapping("/wecom/callback") public class CallbackController {   /**   * The Callback crypto.   */   @Autowired   CallbackCrypto callbackCrypto; ​   /**   * 验证回调URL   *   * @param msgSignature the msg signature   * @param timestamp the timestamp   * @param nonce   the nonce   * @param echostr  the echostr   * @param corpId   the corp id   * @param agentId  the agent id   * @return the long   */   @GetMapping("/{corpId}/{agentId}")   public String verifyUrl(@RequestParam("msg_signature") String msgSignature,              @RequestParam String timestamp,              @RequestParam String nonce,              @RequestParam String echostr,              @PathVariable String corpId,              @PathVariable String agentId) {     return callbackCrypto.decryptMsg(agentId,corpId,msgSignature, timestamp, nonce, echostr);  } ​   /**   * 消费回调数据   *   * @param msgSignature the msg signature   * @param timestamp the timestamp   * @param nonce   the nonce   * @param xmlBody  the xml body   * @param corpId   the corp id   * @param agentId  the agent id   * @return the string   */   @PostMapping("/{corpId}/{agentId}")   public String consume(@RequestParam("msg_signature") String msgSignature,              @RequestParam String timestamp,              @RequestParam String nonce,              @RequestBody String xmlBody,              @PathVariable String corpId,              @PathVariable String agentId) {     return callbackCrypto        .accept(msgSignature, timestamp, nonce, xmlBody);  } ​ } 总结

wecom-sdk总体的设计思路是屏蔽复杂度,提升可用性,并保持可扩展,可复用的理念设计。有兴趣的Java开发者可以参考使用,也欢迎提出意见和参与贡献。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有